package com.hotel.BL;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.EntityName;
import com.StatusTitle;
import com.Util;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.CompositeFilterOperator;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;

import data.CleaningStatus;
import data.CurrencyMaster;
import data.DateTimeFormatMaster;
import data.General;
import data.LanguageMaster;
import data.ReservationStatus;
import data.User;

public class GenericLogic extends AbstractBL {
	
	public GenericLogic(HttpServletRequest req){
		this.req = req;
	}
	
	public GenericLogic(HttpServletRequest req,HttpServletResponse resp){
		this.req = req;
		this.resp = resp;
	}
	
	public List<CleaningStatus> GetCleaningStatus(long hotelId)
	{
		List<CleaningStatus> list = new ArrayList<CleaningStatus>();
		CleaningStatus item;
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.TouchUpRooms) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.TouchUpRooms);
			item.setColor("#B79FE7");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.DirtyRooms) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.DirtyRooms);
			item.setColor("#D6BCBC");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.InspectRooms) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.InspectRooms);
			item.setColor("#E79F9F");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.CleanRooms) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.CleanRooms);
			item.setColor("#FFFFFF");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.RepairRooms) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.RepairRooms);
			item.setColor("#C7C7AD");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetCleaningStatus(hotelId,StatusTitle.CleaningStatusTitle.DNR) == null)
		{
			item = new CleaningStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.DNR);
			item.setColor("#D6AE00");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		return list;
	}
	public CleaningStatus GetCleaningStatus(long hotelId,String cleaningStatus)
	{
		if(cleaningStatus.equals(StatusTitle.CleaningStatusTitle.NoChange))
		{
			return new CleaningStatus();
		}

		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterTitle = new FilterPredicate("title",FilterOperator.EQUAL,cleaningStatus);

		Filter filters = CompositeFilterOperator.and(filterHotel, filterTitle);

		Query q = new Query(EntityName.CleaningStatus).setFilter(filters);
		PreparedQuery pq = datastore.prepare(q);
		try{
			Entity e = pq.asSingleEntity();
			
			CleaningStatus c = new CleaningStatus();
			c.setEntity(e);
			
			return c;
		}
		catch(Exception e) { return null; }
	}
	
	public List<ReservationStatus> GetReservationStatusByHotelId(long hotelId)
	{
		List<ReservationStatus> list = new ArrayList<ReservationStatus>();
		ReservationStatus item;
		
		
		if(GetReservationStatus(hotelId,StatusTitle.ReservationStatus.ReservedRooms) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.ReservationStatus.ReservedRooms);
			item.setColor("#994499");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		
		if(GetReservationStatus(hotelId,StatusTitle.ReservationStatus.CheckedInRooms) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.ReservationStatus.CheckedInRooms);
			item.setColor("#3366CC");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
	
		if(GetReservationStatus(hotelId,StatusTitle.ReservationStatus.CheckedOutRooms) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.ReservationStatus.CheckedOutRooms);
			item.setColor("#CC3333");
			item.setHotelId(hotelId);
			list.add(item);
		}
		

		if(GetReservationStatus(hotelId,StatusTitle.ReservationStatus.TempRooms) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.ReservationStatus.TempRooms);
			item.setColor("#5C8D87");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetReservationStatus(hotelId,StatusTitle.ReservationStatus.CancelReservation) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.ReservationStatus.CancelReservation);
			item.setColor("#FFF");
			item.setHotelId(hotelId);
			list.add(item);
		}
		
		if(GetReservationStatus(hotelId,StatusTitle.CleaningStatusTitle.DNR) == null)
		{
			item = new ReservationStatus();
			item.setTitle(StatusTitle.CleaningStatusTitle.DNR);
			item.setColor("#D6AE00");
			item.setHotelId(hotelId);
			list.add(item);
		}
		return list;
	}
	
	public ReservationStatus GetReservationStatus(long hotelId,String reservationStatus)
	{
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterTitle = new FilterPredicate("title",FilterOperator.EQUAL,reservationStatus);

		Filter filters = CompositeFilterOperator.and(filterHotel, filterTitle);

		Query q = new Query(EntityName.ReservationStatus).setFilter(filters);
		PreparedQuery pq = datastore.prepare(q);
		try{
			Entity e = pq.asSingleEntity();
			
			ReservationStatus r = new ReservationStatus();
			r.setEntity(e);
			
			return r;
		}
		catch(Exception e) { return null; }
	}
	
	public List<ReservationStatus> GetAllReservationStatus(long hotelId) {
		Query q = new Query(EntityName.ReservationStatus);

		Filter filterfhotelId = new FilterPredicate("hotelId", FilterOperator.EQUAL,hotelId);

		
		q.setFilter(filterfhotelId);
		return GetList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	
	public List<ReservationStatus> GetList(List<Entity> entities) {
		List<ReservationStatus> list = new ArrayList<ReservationStatus>();
		if(entities!=null)
		for (Entity e : entities) {
			ReservationStatus a = new ReservationStatus();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
	public List<CleaningStatus> GetAllCleaningStatus(long hotelId) {
		Query q = new Query(EntityName.CleaningStatus);

		Filter filterfhotelId = new FilterPredicate("hotelId", FilterOperator.EQUAL,hotelId);

		
		q.setFilter(filterfhotelId);
		return GetCleaningStatusList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	
	public List<CleaningStatus> GetCleaningStatusList(List<Entity> entities) {
		List<CleaningStatus> list = new ArrayList<CleaningStatus>();
		if(entities!=null)
		for (Entity e : entities) {
			CleaningStatus a = new CleaningStatus();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
	@SuppressWarnings("deprecation")
	public General GenerateGenericData()
	{
		MasterCreator master = new MasterCreator();
				
		General data = new General();
		if(GetGeneral(1) == null){
			data.setHotelId(1);
			data.setUsingLanguageString(String.valueOf(master.GetLanguage(StatusTitle.LanguageTitle.Thai).getId()));
			data.setDefaultLanguage(master.GetLanguage(StatusTitle.LanguageTitle.Thai));
			//data.setUsingCurrency();
			data.setDefaultCurrency(master.GetCurrency(StatusTitle.CurrencyTitle.THB));
			data.setUsingCurrencyString(String.valueOf(master.GetCurrency(StatusTitle.CurrencyTitle.THB).getId()));
			data.setFinancialYearFrom(new Date("2000/1/1"));
			data.setFinancialYearTo(new Date("2000/12/31"));
			data.setCurrencyConversionMargin(3.00);
			data.setCurrencyDecimalPlaces((short) 2);
			data.setInvoicesExclusiveTax(true);
			data.setTaxBreakUp(false);
			data.setAccountFolioOpeningDate(false);
			data.setDateFormat(master.GetDateTimeFormat(StatusTitle.DateTimeFormatTitle.dMyy));
			data.setTimeFormat(true);
			//data.setTimezoneLocation(timezoneLocation);
			data.setCheckInTime(new Date(2001,1,1,14, 0, 0));
			data.setCheckOutTime(new Date(2001,1,1,10, 0, 0));
			data.setNightAuditTime(new Date(2001,1,1,4,0,0));
			data.setAuditUseCalendarDate(false);
			data.setOnNightAuditRollOverMarkOccupied(GetCleaningStatus(1,StatusTitle.CleaningStatusTitle.DirtyRooms));
			data.setOnNightAuditRollOverMarkVacantRoom(GetCleaningStatus(1,StatusTitle.CleaningStatusTitle.NoChange));
			data.setMarkCheckedOutRoom(GetCleaningStatus(1,StatusTitle.CleaningStatusTitle.DirtyRooms));
			data.setIncloudetax(false);
			data.setTimeZone("Asia-Bangkok");
			data.setGMT(7);
			data.setMinuteForWarning(40);
			data.setMinuteForCritical(20);
		}
		else
		{
			data = GetGeneral(1);
			data.setMinuteForWarning(40);
			data.setMinuteForCritical(20);
			data.setUsingLanguageString(String.valueOf(master.GetLanguage(StatusTitle.LanguageTitle.Thai).getId()));
			data.setUsingCurrencyString(String.valueOf(master.GetCurrency(StatusTitle.CurrencyTitle.THB).getId()));
		}
		return data;
	}

	public General GetGeneral(long hotelId)
	{
		Query q = new Query(EntityName.General);
		
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		
		q.setFilter(filterHotel);
		
		return GetGeneral(datastore.prepare(q).asSingleEntity());
	}
	
	public General GetGeneral(Entity entity)
	{
		if(entity == null) return null;
		General item = new General();
		item.setEntity(entity);
		return item;
	}
	
	public General EditIncludeTax(long hotelId) throws EntityNotFoundException{
		General t = GetGeneral(hotelId);
		t.setIncloudetax(false);
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);
		return t;
	}
	
	public General EditDateFormat(long hotelId,String dmyy) throws EntityNotFoundException{
		MasterCreator master = new MasterCreator();
		General t = GetGeneral(hotelId);
		t.setDateFormat(master.GetDateTimeFormat(dmyy));
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);
		return t;
	}
	
	public boolean EditTimeZone(long hotelId,String timeZone , double GMT) throws EntityNotFoundException{
		General t = GetGeneral(hotelId);
		t.setTimeZone(timeZone);
		t.setGMT(GMT);
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);
		return true;
	
	}
	
	public General UpdateGenerlic(General gen) throws EntityNotFoundException
	{
		Key key = datastore.put(gen.getEntity());
		gen.setId(key.getId());
		gen.setKey(key);
		return gen;
	}
	
	public Date ServerDateFromNightAudit(){
		HttpSession session = req.getSession(true);
		long hotelId = 1;
		if (session.getAttribute("hotelId") != null)
			hotelId = (Long) session.getAttribute("hotelId");
		return ServerDateFromNightAudit(hotelId);
	}
	
	public Date ServerDateFromNightAudit(long hotelId){
		Date d = ServerDateTime(hotelId);
		Date nightAuditTime;
		HttpSession session = req.getSession(true);
		if(session.getAttribute("NightAuditTime") != null)
			nightAuditTime = (Date) session.getAttribute("NightAuditTime");
		else{
			General g = GetGeneral( hotelId);
			nightAuditTime = g.getNightAuditTime();
		}
		
		Date nightAudit = Util.GetOnlyDate(d);
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(nightAuditTime);
		
		Calendar cal = Calendar.getInstance();
		cal.setTime(nightAudit);
		cal.set(Calendar.HOUR_OF_DAY,cal2.get(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,cal2.get(Calendar.MINUTE));
		
		Date tmpNightAudit = cal.getTime();
		
		if(d.before(tmpNightAudit))
			return Util.addDays(nightAudit, -1);
		else
			return nightAudit;
	}
	
	public Date TodayNightAuditTime(long hotelId)
	{
		Date d1 = ServerDateFromNightAudit(hotelId);
		Date nightAuditTime;
		HttpSession session = req.getSession(true);
		if(session.getAttribute("NightAuditTime") != null)
			nightAuditTime = (Date) session.getAttribute("NightAuditTime");
		else{
			General g = GetGeneral( hotelId);
			nightAuditTime = g.getNightAuditTime();
		}
		
		Calendar cal2 = Calendar.getInstance();
		cal2.setTime(nightAuditTime);
		
		Calendar cal = Calendar.getInstance();
		cal.setTime(d1);
		cal.set(Calendar.HOUR_OF_DAY,cal2.get(Calendar.HOUR_OF_DAY));
		cal.set(Calendar.MINUTE,cal2.get(Calendar.MINUTE));
		cal.set(Calendar.SECOND,cal2.get(Calendar.SECOND));
		cal.set(Calendar.MILLISECOND,cal2.get(Calendar.MILLISECOND));
		return cal.getTime();
	}

	public Date ServerDateTime()
	{
		HttpSession session = req.getSession(true);
		long hotelId = 1;
		if (session.getAttribute("hotelId") != null)
			hotelId = (Long) session.getAttribute("hotelId");
		return ServerDateTime(hotelId);
	}

	public Date ServerDateTime(long hotelId)
	{
		double gmt;
		HttpSession session = req.getSession(true);
		if(session.getAttribute("GMT") != null)
			gmt = (Double)session.getAttribute("GMT");
		else{
			General g = GetGeneral( hotelId);
			gmt = g.getGMT();
		}
		Date fromDate = Calendar.getInstance().getTime();
		TimeZone tz = TimeZone.getDefault();
		Date ret = new Date( fromDate.getTime() - tz.getRawOffset() );
		return new Date(ret.getTime() +(int)(3600000*gmt)); 
	}
	
	public String ServerDateTimeFormatString(long hotelId){
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.ENGLISH);
		Date serDate = ServerDateTime(hotelId);
		String serverDate = formatter.format(serDate);	
		return serverDate;
	}

	public List<LanguageMaster> GetAllLanguage()
	{
		Query q = new Query(EntityName.Language);
		
		return GetLanguageList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	
	public List<LanguageMaster> GetLanguageList(List<Entity> entities) {
		List<LanguageMaster> list = new ArrayList<LanguageMaster>();
		if(entities!=null)
		for (Entity e : entities) {
			LanguageMaster a = new LanguageMaster();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
	public List<CurrencyMaster> GetAllCurrencyMaster()
	{
		Query q = new Query(EntityName.Currency);
		
		return GetCurrencyMasterList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	
	public List<CurrencyMaster> GetCurrencyMasterList(List<Entity> entities) {
		List<CurrencyMaster> list = new ArrayList<CurrencyMaster>();
		if(entities!=null)
		for (Entity e : entities) {
			CurrencyMaster a = new CurrencyMaster();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
	public List<DateTimeFormatMaster> GetAllDateTimeFormatMaster()
	{
		Query q = new Query(EntityName.DateTimeFormat);
		
		return GetDateTimeFormatMasterList(datastore.prepare(q).asList(FetchOptions.Builder.withDefaults()));
	}
	
	public List<DateTimeFormatMaster> GetDateTimeFormatMasterList(List<Entity> entities) {
		List<DateTimeFormatMaster> list = new ArrayList<DateTimeFormatMaster>();
		if(entities!=null)
		for (Entity e : entities) {
			DateTimeFormatMaster a = new DateTimeFormatMaster();
			a.setEntity(e);
			list.add(a);
		}
		return list;
	}
	
	public ReservationStatus EditReservationStatusColor(long id,String color) throws EntityNotFoundException{
		ReservationStatus t = GetReservationStatus(id);
		t.setColor(color);
		Key k = datastore.put(t.getEntity());
		t.setId(k.getId());
		t.setKey(k);

		return t;
	}
	
	public ReservationStatus GetReservationStatus(long id)
	{
		Key key = KeyFactory.createKey(EntityName.ReservationStatus, id);
		try {
			Entity lang = datastore.get(key);
			ReservationStatus c = new ReservationStatus();
			c.setEntity(lang);
			return c;
		} catch (EntityNotFoundException e) {
			return null;
		}
	}
	
	public CleaningStatus GetCleaningStatusByTitle(long hotelId,String title)
	{
		Query q = new Query(EntityName.CleaningStatus);
		
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		Filter filterTitle = new FilterPredicate("title",FilterOperator.EQUAL,title);
		
		Filter filters = CompositeFilterOperator.and(filterHotel, filterTitle);
		
		q.setFilter(filters);
		
		return GetCleaningStatus(datastore.prepare(q).asSingleEntity());
	}
	
	public CleaningStatus GetCleaningStatus(Entity entity)
	{
		if(entity == null) return null;
		CleaningStatus item = new CleaningStatus();
		item.setEntity(entity);
		return item;
	}

	public boolean ChangePassword(long userid,String oldpass,String newpass){
		User user = new UserLogic(req,resp).GetUser(userid);
		if(user.getPassword().equals(oldpass)){
			user.setPassword(newpass);
			new UserLogic(req,resp).UpdateUser(user);
			return true;
		}else{
			return false;
		}
	}
}

